﻿using System;
using System.Collections.Generic;
using Gameplay.PVE.Utils;
using ImageEffects;
using NodeCanvas.Tasks.Actions;
using RootMotion.FinalIK;
using UnityEngine;
using Yoozoo.Gameplay.RTS;
using Yoozoo.Libs;
using Yoozoo.Managers;

namespace Gameplay.PVE.Survivor
{
    public class RenderComponent: ComponentBase
    {
        
        private BattleGameObject gameObject;

        private Vector3 forward;
        private Vector3 position;

        private ModelHitPoint hitPoint;
        private EModelType modelType;
        private MeshModelRenderer meshModelRenderer;
        private GpuModelRenderer gpuModelRenderer;
        
        private bool hasHpStateDisplay;
        private HpStateDisplay hpStateDisplay;
        
        protected override void OnInitialized()
        {
            modelType = EModelType.None;
            gameObject = BattlePoolManager.Instance.Get(unit.resId);
            gameObject.SetPrefabReadyAction(OnGameObjectReady);
            SetEnabled(SurvivorManager.isUnitRendering);
        }

        public void SetRenderPosition(Vector3 offset,Vector3 forward)
        {
            if (gameObject != null)
            {
                gameObject.Position = offset;
                gameObject.Forward = forward;
            }
        }
        
        protected override void OnUpdate()
        {
            if (unit.isDead)
            {
                UpdateDead();
                return;
            }

            UpdateFlash();
            if (modelType == EModelType.Mesh)
            {
                meshModelRenderer.Update();
            }
            else if (modelType == EModelType.Gpu)
            {
                gpuModelRenderer.Update();
            }
        }
        
        public Vector3 Position
        {
            set
            {
                position = value;
                gameObject.Position = value;
            }
            get => position;
        }
        
        public Vector3 Forward
        {
            set
            {
                forward = value;
                //gameObject.Forward = value;
                if (modelType == EModelType.Gpu)
                {
                    gameObject.Forward = value;
                    //gpuModelRenderer.SetForward(value);
                }
                else if (modelType == EModelType.Mesh)
                {
                    if (!StageManager.Instance.IsInBattle)
                    {
                        gameObject.Forward = value;
                        //meshModelRenderer.Update();
                    }
                }
            }
            get => forward;
        }

        public void RefreshForward()
        {
            gameObject.Forward = forward;
        }
        
        public Transform Parent
        {
            set => gameObject.Parent = value;
        }

        private void UpdateDead()
        {
            var time = TimeManager.time - deadStartTime - dissolveStartTime;
            if (time < 0)
            {
                return;
            }
            
            var amount = time / dissolveDuration;
            amount = Mathf.Clamp01(amount);
            if (modelType == EModelType.Gpu)
            {
                if (!gpuModelRenderer.isDissolving)
                {
                    gpuModelRenderer.StartDissolve();   
                }
                //BattleDebug.LogError(unit.unitId + " 溶解比率 " + amount);
                gpuModelRenderer.SetDissolveAmount(amount);
            }
        }
        
        private void UpdateFlash()
        {
            if (flashStartTime != 0)
            {
                if (Time.time - flashStartTime > flashDuration)
                {
                    float percent = (Time.time - flashStartTime - flashDuration) / (flashFade);
                    if (percent <= 1)
                    {
                        SetFlashAmount(lastFlashAmount * (1 - percent));
                    }
                    else
                    {
                        flashStartTime = 0;
                        SetFlashAmount(0);
                    }
                }
            }
        }

        private void SetFlashAmount(float amount)
        {
            if (modelType == EModelType.Mesh)
            {
                meshModelRenderer.SetFlashAmount(amount);
            }
            else if (modelType == EModelType.Gpu)
            {
                gpuModelRenderer.SetFlashAmount(amount);
            }
        }
        
        private void OnGameObjectReady(GameObject gameObject)
        {
            gameObject.transform.parent = unit.Transform;
            gameObject.transform.localPosition = Vector3.zero;
            gameObject.transform.forward = unit.Forward;
            var modelInstance = gameObject.GetComponent<ModelInstancingGroup>();
            if (modelInstance)
            {
                gpuModelRenderer = ClassManager.Get<GpuModelRenderer>();
                gpuModelRenderer.Initialize(unit,modelInstance);
                modelType = EModelType.Gpu;
            }
            else
            {
                meshModelRenderer = ClassManager.Get<MeshModelRenderer>();
                meshModelRenderer.Initialize(this.unit,gameObject);
                modelType = EModelType.Mesh;
            }
            SetSpeed(0);
            if (unit.rendererReadyCallback != null)
            {
                unit.rendererReadyCallback(gameObject);
                unit.rendererReadyCallback = null;
            }

            
            hpStateDisplay = gameObject.GetComponent<HpStateDisplay>();
            hpStateDisplay?.Init();
            hasHpStateDisplay = hpStateDisplay != null;
        }
        
        public void SetSpeed(float speed,bool immediate = false)
        {
            if (modelType == EModelType.Mesh)
            {
                meshModelRenderer?.SetSpeed(speed,immediate);
            }
            else if (modelType == EModelType.Gpu)
            {
                //BattleDebug.Log(unit.unitId + " Speed = " + speed);
                gpuModelRenderer.SetMoving(speed > 0);
            }
        }

        public void SetBool(string name, bool value)
        {
            meshModelRenderer?.SetBool(name,value);
        }
        
        public void SetFloat(string name, float value)
        {
            meshModelRenderer?.SetFloat(name,value);
        }
        
        private bool isAiming;
        private Transform aimTarget;
        private bool isAimingChanged;

        public Vector3 GetAimForward()
        {
            if (!isAiming)
            {
                return unit.Forward;
            }
            return aimTarget.position - unit.Position;
        }
        
        public void StartAim(Transform target,bool useStartPoint = true)
        {
            isAiming = true;
            aimTarget = target;
            meshModelRenderer?.StartAim(target,useStartPoint);
        }

        public void EndAim()
        {
            isAiming = false;
            aimTarget = null;
            meshModelRenderer?.EndAim();
        }

        public void Play(string name, bool isFullBody = false,bool resetTransition = true)
        {
            if (unit.isDead)
            {
                return;
            }
            if (modelType == EModelType.Gpu)
            {
                gpuModelRenderer?.Play(name,isFullBody,resetTransition);
            }
            else
            {
                meshModelRenderer?.Play(name,isFullBody);
            }
        }
        
        private float flashDuration = 0.03f;
        private float flashFade = 0.03f;
        private float flashStartTime = 0;
        private float lastFlashAmount = 0;

        public void Flash()
        {
            if (unit.isDead)
            {
                return;
            }
            if (gameObject.IsReady)
            {
                lastFlashAmount = 0.7f;
                SetFlashAmount(lastFlashAmount);
                flashStartTime = Time.time;
            }
        }

        private float deadStartTime;
        private float dissolveDuration = 3f;
        private float dissolveStartTime = 2f;
        
        protected override void OnDead()
        {
            base.OnDead();
            deadStartTime = TimeManager.time;
            SetFlashAmount(0);
            flashStartTime = 0;
            this.EndAim();
            if (modelType == EModelType.Mesh)
            {
                meshModelRenderer.OnDead();
            }
            else if (modelType == EModelType.Gpu)
            {
                gpuModelRenderer.OnDead();
            }
        }

        public void SetEnabled(bool enabled)
        {
            if (gameObject != null)
            {
                gameObject.Active = enabled;
            } 
        }

        public void OnLightElementChange()
        {
            meshModelRenderer?.RefreshLightElement();
        }

        public void HideWeapon(int index)
        {
            if (modelType == EModelType.Mesh)
            {
                meshModelRenderer?.HideWeapon(index);
            }
            else if (modelType == EModelType.Gpu)
            {
                gpuModelRenderer?.HideWeapon(index);
            }
        }

        public void SetAnimatorSpeed(float speed)
        {
            if (modelType == EModelType.Mesh)
            {
                meshModelRenderer?.SetAnimatorSpeed(speed);
            }
            else if (modelType == EModelType.Gpu)
            {
                gpuModelRenderer?.SetAnimatorSpeed(speed);
            }
        }

        public void UpdateShadowOffset()
        {
            if (modelType == EModelType.Mesh)
            {
                meshModelRenderer?.UpdateShadowOffset();
            }
        }

        public void OnHpChange()
        {
            if (hasHpStateDisplay)
            {
                hpStateDisplay.OnHpChange((float)unit.currentHp / unit.totalHp);
            }
        }

        public void ShowPhantom()
        {
            if (modelType == EModelType.Mesh)
            {
                meshModelRenderer?.ShowPhantom();
            }
        }
        
        public override void OnReset()
        {
            if (gameObject != null)
            {
                BattlePoolManager.Instance.Release(gameObject);
                gameObject = null;
            }

            hasHpStateDisplay = false;
            hpStateDisplay = null;
            if (meshModelRenderer != null)
            {
                meshModelRenderer.Dispose();
                ClassManager.Free(meshModelRenderer);
                meshModelRenderer = null;
            }
            if (gpuModelRenderer != null)
            {
                gpuModelRenderer.Dispose();
                ClassManager.Free(gpuModelRenderer);
                gpuModelRenderer = null;
            }
            
            forward = default;
            position = default;
            isAiming = false;
            aimTarget = null;

        }
    }
}
